﻿//***********************************************************************
// Assembly         : IGolovkine.AoA.Tests
// Author           : Ilia
// Created          : 06-11-2011
//
// Last Modified By : Ilia
// Last Modified On : 01-04-2010
// Description      : 
//
// Copyright        : (c) Microsoft. All rights reserved.
//***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace IGolovkine.AoA.Tests
{
    public class BlockingSt<M>  : IDisposable
    {
        private readonly Stack<M> _stack;

        public BlockingSt()
        {
            _stack = new Stack<M>();
        }

        public void Push(M item)
        {
            lock (_stack)
            {
                _stack.Push(item);
                Monitor.Pulse(_stack);
            }
        }

        public M Pop(TimeSpan timeout)
        {
            lock (_stack)
            {
                while (_disposed == false)
                {
                    if (_stack.Count != 0)
                    {
                        return _stack.Pop();
                    }

                    if (!Monitor.Wait(_stack, timeout))
                    {
                        throw new TimeoutException("Pop()");
                    }
                }
            }

            throw new ObjectDisposedException("BlockingStack");
        }

        private volatile bool _disposed = false;
        public void Dispose()
        {
            if (_disposed == false)
            {
                _disposed = true;
                lock (_stack)
                {
                    Monitor.PulseAll(_stack);
                    Monitor.Wait(_stack);
                }
            }
        }
    }
}
